home *** CD-ROM | disk | FTP | other *** search
/ MacWorld 2003 August / MW 8 2003 CD1.iso / Inside Macworld / Product News / gimp-1.2.4.sit / gimp-1.2.4 / plug-ins / print / print.c < prev   
Encoding:
C/C++ Source or Header  |  2002-07-20  |  34.9 KB  |  1,315 lines

  1. /*
  2.  * "$Id: print.c,v 1.43.2.2 2002/07/09 16:48:00 neo Exp $"
  3.  *
  4.  *   Print plug-in for the GIMP.
  5.  *
  6.  *   Copyright 1997-2000 Michael Sweet (mike@easysw.com) and
  7.  *    Robert Krawitz (rlk@alum.mit.edu)
  8.  *
  9.  *   This program is free software; you can redistribute it and/or modify it
  10.  *   under the terms of the GNU General Public License as published by the Free
  11.  *   Software Foundation; either version 2 of the License, or (at your option)
  12.  *   any later version.
  13.  *
  14.  *   This program is distributed in the hope that it will be useful, but
  15.  *   WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
  16.  *   or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  17.  *   for more details.
  18.  *
  19.  *   You should have received a copy of the GNU General Public License
  20.  *   along with this program; if not, write to the Free Software
  21.  *   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  22.  */
  23.  
  24. #include "config.h"
  25.  
  26. #include <stdlib.h>
  27. #include <sys/types.h>
  28. #include <signal.h>
  29. #include <ctype.h>
  30. #include <sys/wait.h>
  31. #ifdef __EMX__
  32. #define INCL_DOSDEVICES
  33. #define INCL_DOSERRORS
  34. #include <os2.h>
  35. #endif
  36.  
  37. #include <unistd.h>
  38. #include <stdio.h>
  39. #include <string.h>
  40.  
  41. #include <gimp-print/gimp-print.h>
  42.  
  43. #include "libgimp/gimp.h"
  44. #include "libgimp/gimpui.h"
  45.  
  46. #include "print_gimp.h"
  47.  
  48. #include "libgimp/stdplugins-intl.h"
  49.  
  50. /*
  51.  * Local functions...
  52.  */
  53.  
  54. static void    printrc_load (void);
  55. void        printrc_save (void);
  56. static int    compare_printers (gp_plist_t *p1, gp_plist_t *p2);
  57. static void    get_system_printers (void);
  58.  
  59. static void    query (void);
  60. static void    run (char *, int, GimpParam *, int *, GimpParam **);
  61. static int    do_print_dialog (char *proc_name);
  62.  
  63. /*
  64.  * Globals...
  65.  */
  66.  
  67. GimpPlugInInfo    PLUG_IN_INFO =        /* Plug-in information */
  68. {
  69.   NULL,  /* init_proc  */
  70.   NULL,  /* quit_proc  */
  71.   query, /* query_proc */
  72.   run,   /* run_proc   */
  73. };
  74.  
  75. stp_vars_t vars = NULL;
  76.  
  77. int        plist_current = 0,    /* Current system printer */
  78.         plist_count = 0;    /* Number of system printers */
  79. gp_plist_t        *plist;            /* System printers */
  80.  
  81. int        saveme = FALSE;        /* True if print should proceed */
  82. int        runme = FALSE;        /* True if print should proceed */
  83. stp_printer_t current_printer = 0;    /* Current printer index */
  84. gint32          image_ID;            /* image ID */
  85.  
  86. const char *image_filename;
  87. int image_width;
  88. int image_height;
  89.  
  90. static void
  91. check_plist(int count)
  92. {
  93.   static int current_plist_size = 0;
  94.   if (count <= current_plist_size)
  95.     return;
  96.   else if (current_plist_size == 0)
  97.     {
  98.       current_plist_size = count;
  99.       plist = g_malloc (current_plist_size * sizeof(gp_plist_t));
  100.     }
  101.   else
  102.     {
  103.       current_plist_size *= 2;
  104.       if (current_plist_size < count)
  105.     current_plist_size = count;
  106.       plist = g_realloc (plist, current_plist_size * sizeof(gp_plist_t));
  107.     }
  108. }
  109.  
  110. /*
  111.  * 'main()' - Main entry - just call gimp_main()...
  112.  */
  113.  
  114. MAIN()
  115.  
  116. static int print_finished = 0;
  117.  
  118. /*
  119.  * 'query()' - Respond to a plug-in query...
  120.  */
  121.  
  122. static void
  123. query (void)
  124. {
  125.   static GimpParamDef args[] =
  126.   {
  127.     { GIMP_PDB_INT32,    "run_mode",    "Interactive, non-interactive" },
  128.     { GIMP_PDB_IMAGE,    "image",    "Input image" },
  129.     { GIMP_PDB_DRAWABLE,    "drawable",    "Input drawable" },
  130.     { GIMP_PDB_STRING,    "output_to",    "Print command or filename (| to pipe to command)" },
  131.     { GIMP_PDB_STRING,    "driver",    "Printer driver short name" },
  132.     { GIMP_PDB_STRING,    "ppd_file",    "PPD file" },
  133.     { GIMP_PDB_INT32,    "output_type",    "Output type (0 = gray, 1 = color)" },
  134.     { GIMP_PDB_STRING,    "resolution",    "Resolution (\"300\", \"720\", etc.)" },
  135.     { GIMP_PDB_STRING,    "media_size",    "Media size (\"Letter\", \"A4\", etc.)" },
  136.     { GIMP_PDB_STRING,    "media_type",    "Media type (\"Plain\", \"Glossy\", etc.)" },
  137.     { GIMP_PDB_STRING,    "media_source",    "Media source (\"Tray1\", \"Manual\", etc.)" },
  138.     { GIMP_PDB_FLOAT,    "brightness",    "Brightness (0-400%)" },
  139.     { GIMP_PDB_FLOAT,    "scaling",    "Output scaling (0-100%, -PPI)" },
  140.     { GIMP_PDB_INT32,    "orientation",    "Output orientation (-1 = auto, 0 = portrait, 1 = landscape)" },
  141.     { GIMP_PDB_INT32,    "left",        "Left offset (points, -1 = centered)" },
  142.     { GIMP_PDB_INT32,    "top",        "Top offset (points, -1 = centered)" },
  143.     { GIMP_PDB_FLOAT,    "gamma",    "Output gamma (0.1 - 3.0)" },
  144.     { GIMP_PDB_FLOAT,    "contrast",    "Contrast" },
  145.     { GIMP_PDB_FLOAT,    "cyan",        "Cyan level" },
  146.     { GIMP_PDB_FLOAT,    "magenta",    "Magenta level" },
  147.     { GIMP_PDB_FLOAT,    "yellow",        "Yellow level" },
  148.     { GIMP_PDB_INT32,    "linear",    "Linear output (0 = normal, 1 = linear)" },
  149.     { GIMP_PDB_INT32,    "image_type",    "Image type (0 = line art, 1 = solid tones, 2 = continuous tone, 3 = monochrome)"},
  150.     { GIMP_PDB_FLOAT,    "saturation",    "Saturation (0-1000%)" },
  151.     { GIMP_PDB_FLOAT,    "density",    "Density (0-200%)" },
  152.     { GIMP_PDB_STRING,    "ink_type",    "Type of ink or cartridge" },
  153.     { GIMP_PDB_STRING,    "dither_algorithm", "Dither algorithm" },
  154.     { GIMP_PDB_INT32,    "unit",        "Unit 0=Inches 1=Metric" },
  155.   };
  156.   static gint nargs = sizeof(args) / sizeof(args[0]);
  157.  
  158.   static gchar *blurb = "This plug-in prints images from The GIMP.";
  159.   static gchar *help  = "Prints images to PostScript, PCL, or ESC/P2 printers.";
  160.   static gchar *auth  = "Michael Sweet <mike@easysw.com> and Robert Krawitz <rlk@alum.mit.edu>";
  161.   static gchar *copy  = "Copyright 1997-2000 by Michael Sweet and Robert Krawitz";
  162.   static gchar *types = "RGB*,GRAY*,INDEXED*";
  163.  
  164.   gimp_install_procedure ("file_print_gimp",
  165.               blurb, help, auth, copy,
  166.               PLUG_IN_VERSION,
  167.               N_("<Image>/File/Print..."),
  168.               types,
  169.               GIMP_PLUGIN,
  170.               nargs, 0,
  171.               args, NULL);
  172. }
  173.  
  174. #ifdef __EMX__
  175. static char *
  176. get_tmp_filename()
  177. {
  178.   char *tmp_path, *s, filename[80];
  179.  
  180.   tmp_path = getenv("TMP");
  181.   if (tmp_path == NULL)
  182.     tmp_path = "";
  183.  
  184.   sprintf(filename, "gimp_print_tmp.%d", getpid());
  185.   s = tmp_path = g_strconcat(tmp_path, "\\", filename, NULL);
  186.   if (!s)
  187.     return NULL;
  188.   for ( ; *s; s++)
  189.     if (*s == '/') *s = '\\';
  190.   return tmp_path;
  191. }
  192. #endif
  193.  
  194. /*
  195.  * 'usr1_handler()' - Make a note when we receive SIGUSR1.
  196.  */
  197.  
  198. static volatile int usr1_interrupt;
  199.  
  200. static void
  201. usr1_handler (int signal)
  202. {
  203.   usr1_interrupt = 1;
  204. }
  205.  
  206. void
  207. gimp_writefunc(void *file, const char *buf, size_t bytes)
  208. {
  209.   FILE *prn = (FILE *)file;
  210.   fwrite(buf, 1, bytes, prn);
  211. }
  212.  
  213. /*
  214.  * 'run()' - Run the plug-in...
  215.  */
  216.  
  217. /* #define DEBUG_STARTUP */
  218.  
  219. #ifdef DEBUG_STARTUP
  220. volatile int SDEBUG = 1;
  221. #endif
  222.  
  223. static void
  224. run (char   *name,        /* I - Name of print program. */
  225.      int    nparams,        /* I - Number of parameters passed in */
  226.      GimpParam *param,        /* I - Parameter values */
  227.      int    *nreturn_vals,    /* O - Number of return values */
  228.      GimpParam **return_vals)    /* O - Return values */
  229. {
  230.   GimpDrawable    *drawable;    /* Drawable for image */
  231.   GimpRunModeType     run_mode;    /* Current run mode */
  232.   FILE        *prn = NULL;    /* Print file/command */
  233.   int         ncolors;    /* Number of colors in colormap */
  234.   GimpParam    *values;    /* Return values */
  235. #ifdef __EMX__
  236.   char        *tmpfile;    /* temp filename */
  237. #endif
  238.   gint32         drawable_ID;   /* drawable ID */
  239.   GimpExportReturnType export = GIMP_EXPORT_CANCEL;    /* return value of gimp_export_image() */
  240.   int        ppid = getpid (), /* PID of plugin */
  241.         opid,        /* PID of output process */
  242.         cpid = 0,    /* PID of control/monitor process */
  243.         pipefd[2];    /* Fds of the pipe connecting all the above */
  244.   int        dummy;
  245. #ifdef DEBUG_STARTUP
  246.   while (SDEBUG)
  247.     ;
  248. #endif
  249.  
  250.  /*
  251.   * Initialise libgimpprint
  252.   */
  253.  
  254.   stp_init();
  255.  
  256.   INIT_I18N_UI();
  257.  
  258.   vars = stp_allocate_copy(stp_default_settings());
  259.   stp_set_input_color_model(vars, COLOR_MODEL_RGB);
  260.   stp_set_output_color_model(vars, COLOR_MODEL_RGB);
  261.   /*
  262.    * Initialize parameter data...
  263.    */
  264.  
  265.   current_printer = stp_get_printer_by_index (0);
  266.   run_mode = (GimpRunModeType)param[0].data.d_int32;
  267.  
  268.   values = g_new (GimpParam, 1);
  269.  
  270.   values[0].type          = GIMP_PDB_STATUS;
  271.   values[0].data.d_status = GIMP_PDB_SUCCESS;
  272.  
  273.   *nreturn_vals = 1;
  274.   *return_vals  = values;
  275.  
  276.   image_ID = param[1].data.d_int32;
  277.   drawable_ID = param[2].data.d_int32;
  278.  
  279.   image_filename = gimp_image_get_filename (image_ID);
  280.   if (strchr(image_filename, '/'))
  281.     image_filename = strrchr(image_filename, '/') + 1;
  282.  
  283.   /*  eventually export the image */
  284.   switch (run_mode)
  285.     {
  286.     case GIMP_RUN_INTERACTIVE:
  287.     case GIMP_RUN_WITH_LAST_VALS:
  288.       gimp_ui_init ("print", TRUE);
  289.       export = gimp_export_image (&image_ID, &drawable_ID, "Print",
  290.                   (GIMP_EXPORT_CAN_HANDLE_RGB |
  291.                    GIMP_EXPORT_CAN_HANDLE_GRAY |
  292.                    GIMP_EXPORT_CAN_HANDLE_INDEXED |
  293.                    GIMP_EXPORT_CAN_HANDLE_ALPHA));
  294.       if (export == GIMP_EXPORT_CANCEL)
  295.     {
  296.       *nreturn_vals = 1;
  297.       values[0].data.d_status = GIMP_PDB_EXECUTION_ERROR;
  298.       return;
  299.     }
  300.       break;
  301.     default:
  302.       break;
  303.     }
  304.  
  305.   /*
  306.    * Get drawable...
  307.    */
  308.  
  309.   drawable = gimp_drawable_get (drawable_ID);
  310.  
  311.   image_width  = drawable->width;
  312.   image_height = drawable->height;
  313.  
  314.   /*
  315.    * See how we will run
  316.    */
  317.  
  318.   switch (run_mode)
  319.     {
  320.     case GIMP_RUN_INTERACTIVE:
  321.       /*
  322.        * Get information from the dialog...
  323.        */
  324.  
  325.       if (!do_print_dialog (name))
  326.     goto cleanup;
  327.       stp_copy_vars(vars, plist[plist_current].v);
  328.       break;
  329.  
  330.     case GIMP_RUN_NONINTERACTIVE:
  331.       /*
  332.        * Make sure all the arguments are present...
  333.        */
  334.       if (nparams < 11)
  335.     values[0].data.d_status = GIMP_PDB_CALLING_ERROR;
  336.       else
  337.     {
  338.       stp_set_output_to(vars, param[3].data.d_string);
  339.       stp_set_driver(vars, param[4].data.d_string);
  340.       stp_set_ppd_file(vars, param[5].data.d_string);
  341.       stp_set_output_type(vars, param[6].data.d_int32);
  342.       stp_set_resolution(vars, param[7].data.d_string);
  343.       stp_set_media_size(vars, param[8].data.d_string);
  344.       stp_set_media_type(vars, param[9].data.d_string);
  345.       stp_set_media_source(vars, param[10].data.d_string);
  346.  
  347.           if (nparams > 11)
  348.         stp_set_brightness(vars, param[11].data.d_float);
  349.  
  350.           if (nparams > 12)
  351.             stp_set_scaling(vars, param[12].data.d_float);
  352.  
  353.           if (nparams > 13)
  354.             stp_set_orientation(vars, param[13].data.d_int32);
  355.  
  356.           if (nparams > 14)
  357.             stp_set_left(vars, param[14].data.d_int32);
  358.  
  359.           if (nparams > 15)
  360.             stp_set_top(vars, param[15].data.d_int32);
  361.  
  362.           if (nparams > 16)
  363.             stp_set_gamma(vars, param[16].data.d_float);
  364.  
  365.           if (nparams > 17)
  366.         stp_set_contrast(vars, param[17].data.d_float);
  367.  
  368.           if (nparams > 18)
  369.         stp_set_cyan(vars, param[18].data.d_float);
  370.  
  371.           if (nparams > 19)
  372.         stp_set_magenta(vars, param[19].data.d_float);
  373.  
  374.           if (nparams > 20)
  375.         stp_set_yellow(vars, param[20].data.d_float);
  376.  
  377.           if (nparams > 21)
  378.             stp_set_image_type(vars, param[22].data.d_int32);
  379.  
  380.           if (nparams > 22)
  381.             stp_set_saturation(vars, param[23].data.d_float);
  382.  
  383.           if (nparams > 23)
  384.             stp_set_density(vars, param[24].data.d_float);
  385.  
  386.       if (nparams > 24)
  387.         stp_set_ink_type(vars, param[25].data.d_string);
  388.  
  389.       if (nparams > 25)
  390.         stp_set_dither_algorithm(vars, param[26].data.d_string);
  391.  
  392.           if (nparams > 26)
  393.             stp_set_unit(vars, param[27].data.d_int32);
  394.     }
  395.  
  396.       current_printer = stp_get_printer_by_driver (stp_get_driver(vars));
  397.       break;
  398.  
  399.     case GIMP_RUN_WITH_LAST_VALS:
  400.       values[0].data.d_status = GIMP_PDB_CALLING_ERROR;
  401.       break;
  402.  
  403.     default:
  404.       values[0].data.d_status = GIMP_PDB_CALLING_ERROR;
  405.       break;
  406.     }
  407.  
  408.   /*
  409.    * Print the image...
  410.    */
  411.   if (values[0].data.d_status == GIMP_PDB_SUCCESS)
  412.     {
  413.       /*
  414.        * Set the tile cache size...
  415.        */
  416.  
  417.       if (drawable->height > drawable->width)
  418.     gimp_tile_cache_ntiles ((drawable->height + gimp_tile_width () - 1) /
  419.                 gimp_tile_width () + 1);
  420.       else
  421.     gimp_tile_cache_ntiles ((drawable->width + gimp_tile_width () - 1) /
  422.                 gimp_tile_width () + 1);
  423.  
  424.       /*
  425.        * Open the file/execute the print command...
  426.        */
  427.  
  428.       if (plist_current > 0)
  429. #ifndef __EMX__
  430.       {
  431.     /*
  432.      * The following IPC code is only necessary because the GIMP kills
  433.      * plugins with SIGKILL if its "Cancel" button is pressed; this
  434.      * gives the plugin no chance whatsoever to clean up after itself.
  435.      */
  436.     usr1_interrupt = 0;
  437.     signal (SIGUSR1, usr1_handler);
  438.     if (pipe (pipefd) != 0) {
  439.       prn = NULL;
  440.     } else {
  441.       cpid = fork ();
  442.       if (cpid < 0) {
  443.         prn = NULL;
  444.       } else if (cpid == 0) {
  445.         /* LPR monitor process.  Printer output is piped to us. */
  446.         opid = fork ();
  447.         if (opid < 0) {
  448.           /* Errors will cause the plugin to get a SIGPIPE.  */
  449.           exit (1);
  450.         } else if (opid == 0) {
  451.           dup2 (pipefd[0], 0);
  452.           close (pipefd[0]);
  453.           close (pipefd[1]);
  454.           execl("/bin/sh", "/bin/sh", "-c", stp_get_output_to(vars), NULL);
  455.           /* NOTREACHED */
  456.           exit (1);
  457.         } else {
  458.           /*
  459.            * If the print plugin gets SIGKILLed by gimp, we kill lpr
  460.            * in turn.  If the plugin signals us with SIGUSR1 that it's
  461.            * finished printing normally, we close our end of the pipe,
  462.            * and go away.
  463.            */
  464.           close (pipefd[0]);
  465.           while (usr1_interrupt == 0) {
  466.             if (kill (ppid, 0) < 0) {
  467.           /* The print plugin has been killed!  */
  468.           kill (opid, SIGTERM);
  469.           waitpid (opid, &dummy, 0);
  470.           close (pipefd[1]);
  471.           /*
  472.            * We do not want to allow cleanup before exiting.
  473.            * The exiting parent has already closed the connection
  474.            * to the X server; if we try to clean up, we'll notice
  475.            * that fact and complain.
  476.            */
  477.           _exit (0);
  478.             }
  479.             sleep (5);
  480.           }
  481.           /* We got SIGUSR1.  */
  482.           close (pipefd[1]);
  483.           /*
  484.            * We do not want to allow cleanup before exiting.
  485.            * The exiting parent has already closed the connection
  486.            * to the X server; if we try to clean up, we'll notice
  487.            * that fact and complain.
  488.            */
  489.           _exit (0);
  490.         }
  491.       } else {
  492.         close (pipefd[0]);
  493.         /* Parent process.  We generate the printer output. */
  494.         prn = fdopen (pipefd[1], "w");
  495.         /* and fall through... */
  496.       }
  497.     }
  498.       }
  499. #else
  500.       /* OS/2 PRINT command doesn't support print from stdin, use temp file */
  501.       prn = (tmpfile = get_tmp_filename ()) ? fopen (tmpfile, "w") : NULL;
  502. #endif
  503.       else
  504.     prn = fopen (stp_get_output_to(vars), "wb");
  505.  
  506.       if (prn != NULL)
  507.     {
  508.       stp_image_t *image = Image_GimpDrawable_new(drawable);
  509.       stp_set_app_gamma(vars, gimp_gamma());
  510.       stp_merge_printvars(vars, stp_printer_get_printvars(current_printer));
  511.  
  512.       /*
  513.        * Is the image an Indexed type?  If so we need the colormap...
  514.        */
  515.  
  516.       if (gimp_image_base_type (image_ID) == GIMP_INDEXED)
  517.         stp_set_cmap(vars, gimp_image_get_cmap (image_ID, &ncolors));
  518.       else
  519.         stp_set_cmap(vars, NULL);
  520.  
  521.       /*
  522.        * Finally, call the print driver to send the image to the printer
  523.        * and close the output file/command...
  524.        */
  525.  
  526.       stp_set_outfunc(vars, gimp_writefunc);
  527.       stp_set_errfunc(vars, gimp_writefunc);
  528.       stp_set_outdata(vars, prn);
  529.       stp_set_errdata(vars, stderr);
  530.       if (stp_printer_get_printfuncs(current_printer)->verify
  531.           (current_printer, vars))
  532.         stp_printer_get_printfuncs(current_printer)->print
  533.           (current_printer, image, vars);
  534.       else
  535.         values[0].data.d_status = GIMP_PDB_EXECUTION_ERROR;
  536.  
  537.       if (plist_current > 0)
  538. #ifndef __EMX__
  539.       {
  540.         fclose (prn);
  541.         kill (cpid, SIGUSR1);
  542.         waitpid (cpid, &dummy, 0);
  543.       }
  544. #else
  545.       { /* PRINT temp file */
  546.         char *s;
  547.         fclose (prn);
  548.         s = g_strconcat (stp_get_output_to(vars), tmpfile, NULL);
  549.         if (system(s) != 0)
  550.           values[0].data.d_status = GIMP_PDB_EXECUTION_ERROR;
  551.         g_free (s);
  552.         remove (tmpfile);
  553.         g_free (tmpfile);
  554.       }
  555. #endif
  556.       else
  557.         fclose (prn);
  558.       print_finished = 1;
  559.     }
  560.       else
  561.     values[0].data.d_status = GIMP_PDB_EXECUTION_ERROR;
  562.  
  563.       /*
  564.        * Store data...
  565.        */
  566.  
  567.       if (run_mode == GIMP_RUN_INTERACTIVE)
  568.     gimp_set_data (PLUG_IN_NAME, vars, sizeof (vars));
  569.     }
  570.  
  571.   /*
  572.    * Detach from the drawable...
  573.    */
  574.   gimp_drawable_detach (drawable);
  575.  
  576.  cleanup:
  577.   if (export == GIMP_EXPORT_EXPORT)
  578.     gimp_image_delete (image_ID);
  579.   stp_free_vars(vars);
  580. }
  581.  
  582. /*
  583.  * 'do_print_dialog()' - Pop up the print dialog...
  584.  */
  585.  
  586. static gint
  587. do_print_dialog (gchar *proc_name)
  588. {
  589.  
  590.   /*
  591.    * Get printrc options...
  592.    */
  593.   printrc_load ();
  594.  
  595.   /*
  596.    * Print dialog window...
  597.    */
  598.   gimp_create_main_window();
  599.  
  600.   gtk_main ();
  601.   gdk_flush ();
  602.  
  603.   /*
  604.    * Set printrc options...
  605.    */
  606.   if (saveme)
  607.     printrc_save ();
  608.  
  609.   /*
  610.    * Return ok/cancel...
  611.    */
  612.   return (runme);
  613. }
  614.  
  615. void
  616. initialize_printer(gp_plist_t *printer)
  617. {
  618.   printer->name[0] = '\0';
  619.   printer->active=0;
  620.   printer->v = stp_allocate_vars();
  621. }
  622.  
  623. #define GET_MANDATORY_INTERNAL_STRING_PARAM(param)    \
  624. do {                            \
  625.   if ((commaptr = strchr(lineptr, ',')) == NULL)    \
  626.     continue;                        \
  627.   strncpy(key.param, lineptr, commaptr - line);        \
  628.   key.param[commaptr - lineptr] = '\0';            \
  629.   lineptr = commaptr + 1;                \
  630. } while (0)
  631.  
  632. #define GET_MANDATORY_STRING_PARAM(param)        \
  633. do {                            \
  634.   if ((commaptr = strchr(lineptr, ',')) == NULL)    \
  635.     continue;                        \
  636.   stp_set_##param##_n(key.v, lineptr, commaptr - line);    \
  637.   lineptr = commaptr + 1;                \
  638. } while (0)
  639.  
  640. #define GET_MANDATORY_INT_PARAM(param)            \
  641. do {                            \
  642.   if ((commaptr = strchr(lineptr, ',')) == NULL)    \
  643.     continue;                        \
  644.   stp_set_##param(key.v, atoi(lineptr));        \
  645.   lineptr = commaptr + 1;                \
  646. } while (0)
  647.  
  648. #define GET_OPTIONAL_STRING_PARAM(param)            \
  649. do {                                \
  650.   if ((commaptr = strchr(lineptr, ',')) == NULL)        \
  651.     {                                \
  652.       stp_set_##param(key.v, lineptr);                \
  653.       keepgoing = 0;                        \
  654.     }                                \
  655.   else                                \
  656.     {                                \
  657.       stp_set_##param##_n(key.v, lineptr, commaptr - lineptr);    \
  658.       lineptr = commaptr + 1;                    \
  659.     }                                \
  660. } while (0)
  661.  
  662. #define GET_OPTIONAL_INT_PARAM(param)                    \
  663. do {                                    \
  664.   if ((keepgoing == 0) || ((commaptr = strchr(lineptr, ',')) == NULL))    \
  665.     {                                    \
  666.       keepgoing = 0;                            \
  667.     }                                    \
  668.   else                                    \
  669.     {                                    \
  670.       stp_set_##param(key.v, atoi(lineptr));                \
  671.       lineptr = commaptr + 1;                        \
  672.     }                                    \
  673. } while (0)
  674.  
  675. #define IGNORE_OPTIONAL_PARAM(param)                    \
  676. do {                                    \
  677.   if ((keepgoing == 0) || ((commaptr = strchr(lineptr, ',')) == NULL))    \
  678.     {                                    \
  679.       keepgoing = 0;                            \
  680.     }                                    \
  681.   else                                    \
  682.     {                                    \
  683.       lineptr = commaptr + 1;                        \
  684.     }                                    \
  685. } while (0)
  686.  
  687. #define GET_OPTIONAL_FLOAT_PARAM(param)                    \
  688. do {                                    \
  689.   if ((keepgoing == 0) || ((commaptr = strchr(lineptr, ',')) == NULL))    \
  690.     {                                    \
  691.       keepgoing = 0;                            \
  692.     }                                    \
  693.   else                                    \
  694.     {                                    \
  695.       const stp_vars_t maxvars = stp_maximum_settings();        \
  696.       const stp_vars_t minvars = stp_minimum_settings();        \
  697.       const stp_vars_t defvars = stp_default_settings();        \
  698.       stp_set_##param(key.v, atof(lineptr));                \
  699.       if (stp_get_##param(key.v) > 0 &&                    \
  700.       (stp_get_##param(key.v) > stp_get_##param(maxvars) ||        \
  701.        stp_get_##param(key.v) < stp_get_##param(minvars)))        \
  702.     stp_set_##param(key.v, stp_get_##param(defvars));        \
  703.       lineptr = commaptr + 1;                        \
  704.     }                                    \
  705. } while (0)
  706.  
  707. static void *
  708. psearch(const void *key, const void *base, size_t nmemb, size_t size,
  709.     int (*compar)(const void *, const void *))
  710. {
  711.   int i;
  712.   const char *cbase = (const char *) base;
  713.   for (i = 0; i < nmemb; i++)
  714.     {
  715.       if ((*compar)(key, (const void *) cbase) == 0)
  716.     return (void *) cbase;
  717.       cbase += size;
  718.     }
  719.   return NULL;
  720. }
  721.  
  722. int
  723. add_printer(const gp_plist_t *key, int add_only)
  724. {
  725.   /*
  726.    * The format of the list is the File printer followed by a qsort'ed list
  727.    * of system printers. So, if we want to update the file printer, it is
  728.    * always first in the list, else call psearch.
  729.    */
  730.   gp_plist_t *p;
  731.   if (strcmp(_("File"), key->name) == 0
  732.       && strcmp(plist[0].name, _("File")) == 0)
  733.     {
  734.       if (add_only)
  735.     return 0;
  736.       if (stp_get_printer_by_driver(stp_get_driver(key->v)))
  737.     {
  738. #ifdef DEBUG
  739.       printf("Updated File printer directly\n");
  740. #endif
  741.       p = &plist[0];
  742.       memcpy(p, key, sizeof(gp_plist_t));
  743.       p->v = stp_allocate_copy(key->v);
  744.       p->active = 1;
  745.     }
  746.       return 1;
  747.     }
  748.   else if (stp_get_printer_by_driver(stp_get_driver(key->v)))
  749.     {
  750.       p = psearch(key, plist + 1, plist_count - 1,
  751.           sizeof(gp_plist_t),
  752.           (int (*)(const void *, const void *)) compare_printers);
  753.       if (p == NULL)
  754.     {
  755. #ifdef DEBUG
  756.       fprintf(stderr, "Adding new printer from printrc file: %s\n",
  757.           key->name);
  758. #endif
  759.       check_plist(plist_count + 1);
  760.       p = plist + plist_count;
  761.       plist_count++;
  762.       memcpy(p, key, sizeof(gp_plist_t));
  763.       p->v = stp_allocate_copy(key->v);
  764.       p->active = 0;
  765.     }
  766.       else
  767.     {
  768.       if (add_only)
  769.         return 0;
  770. #ifdef DEBUG
  771.       printf("Updating printer %s.\n", key->name);
  772. #endif
  773.       memcpy(p, key, sizeof(gp_plist_t));
  774.       stp_copy_vars(p->v, key->v);
  775.       p->active = 1;
  776.     }
  777.     }
  778.   return 1;
  779. }
  780.  
  781. /*
  782.  * 'printrc_load()' - Load the printer resource configuration file.
  783.  */
  784. void
  785. printrc_load(void)
  786. {
  787.   int        i;        /* Looping var */
  788.   FILE        *fp;        /* Printrc file */
  789.   char        *filename;    /* Its name */
  790.   char        line[1024],    /* Line in printrc file */
  791.         *lineptr,    /* Pointer in line */
  792.         *commaptr;    /* Pointer to next comma */
  793.   gp_plist_t    key;        /* Search key */
  794.   int        format = 0;    /* rc file format version */
  795.   int        system_printers; /* printer count before reading printrc */
  796.   char *    current_printer = 0; /* printer to select */
  797.  
  798.   check_plist(1);
  799.  
  800.  /*
  801.   * Get the printer list...
  802.   */
  803.  
  804.   get_system_printers();
  805.  
  806.   system_printers = plist_count - 1;
  807.  
  808.  /*
  809.   * Generate the filename for the current user...
  810.   */
  811.  
  812.   filename = gimp_personal_rc_file ("printrc");
  813.  
  814. #ifdef __EMX__
  815.   _fnslashify(filename);
  816. #endif
  817.  
  818. #ifndef __EMX__
  819.   if ((fp = fopen(filename, "r")) != NULL)
  820. #else
  821.   if ((fp = fopen(filename, "rt")) != NULL)
  822. #endif
  823.   {
  824.    /*
  825.     * File exists - read the contents and update the printer list...
  826.     */
  827.  
  828.     (void) memset(&key, 0, sizeof(gp_plist_t));
  829.     initialize_printer(&key);
  830.     strcpy(key.name, _("File"));
  831.     (void) memset(line, 0, 1024);
  832.     while (fgets(line, sizeof(line), fp) != NULL)
  833.     {
  834.       int keepgoing = 1;
  835.       if (line[0] == '#')
  836.       {
  837.     if (strncmp("#PRINTRCv", line, 9) == 0)
  838.     {
  839. #ifdef DEBUG
  840.           printf("Found printrc version tag: `%s'\n", line);
  841.           printf("Version number: `%s'\n", &(line[9]));
  842. #endif
  843.       (void) sscanf(&(line[9]), "%d", &format);
  844.     }
  845.         continue;    /* Comment */
  846.       }
  847.       if (format == 0)
  848.       {
  849.        /*
  850.     * Read old format printrc lines...
  851.     */
  852.  
  853.         initialize_printer(&key);
  854.         lineptr = line;
  855.  
  856.        /*
  857.         * Read the command-delimited printer definition data.  Note that
  858.         * we can't use sscanf because %[^,] fails if the string is empty...
  859.         */
  860.  
  861.         GET_MANDATORY_INTERNAL_STRING_PARAM(name);
  862.         GET_MANDATORY_STRING_PARAM(output_to);
  863.         GET_MANDATORY_STRING_PARAM(driver);
  864.  
  865.         if (! stp_get_printer_by_driver(stp_get_driver(key.v)))
  866.       continue;
  867.  
  868.         GET_MANDATORY_STRING_PARAM(ppd_file);
  869.         GET_MANDATORY_INT_PARAM(output_type);
  870.         GET_MANDATORY_STRING_PARAM(resolution);
  871.         GET_MANDATORY_STRING_PARAM(media_size);
  872.         GET_MANDATORY_STRING_PARAM(media_type);
  873.  
  874.         GET_OPTIONAL_STRING_PARAM(media_source);
  875.         GET_OPTIONAL_FLOAT_PARAM(brightness);
  876.         GET_OPTIONAL_FLOAT_PARAM(scaling);
  877.         GET_OPTIONAL_INT_PARAM(orientation);
  878.         GET_OPTIONAL_INT_PARAM(left);
  879.         GET_OPTIONAL_INT_PARAM(top);
  880.         GET_OPTIONAL_FLOAT_PARAM(gamma);
  881.         GET_OPTIONAL_FLOAT_PARAM(contrast);
  882.         GET_OPTIONAL_FLOAT_PARAM(cyan);
  883.         GET_OPTIONAL_FLOAT_PARAM(magenta);
  884.         GET_OPTIONAL_FLOAT_PARAM(yellow);
  885.         IGNORE_OPTIONAL_PARAM(linear);
  886.         GET_OPTIONAL_INT_PARAM(image_type);
  887.         GET_OPTIONAL_FLOAT_PARAM(saturation);
  888.         GET_OPTIONAL_FLOAT_PARAM(density);
  889.         GET_OPTIONAL_STRING_PARAM(ink_type);
  890.         GET_OPTIONAL_STRING_PARAM(dither_algorithm);
  891.         GET_OPTIONAL_INT_PARAM(unit);
  892.     add_printer(&key, 0);
  893.       }
  894.       else if (format == 1)
  895.       {
  896.        /*
  897.     * Read new format printrc lines...
  898.     */
  899.  
  900.     char *keyword, *end, *value;
  901.  
  902.     keyword = line;
  903.     for (keyword = line; isspace(*keyword); keyword++)
  904.     {
  905.       /* skip initial spaces... */
  906.     }
  907.     if (!isalpha(*keyword))
  908.       continue;
  909.     for (end = keyword; isalnum(*end) || *end == '-'; end++)
  910.     {
  911.       /* find end of keyword... */
  912.     }
  913.     value = end;
  914.     while (isspace(*value)) {
  915.       /* skip over white space... */
  916.       value++;
  917.     }
  918.     if (*value != ':')
  919.       continue;
  920.     value++;
  921.     *end = '\0';
  922.     while (isspace(*value)) {
  923.       /* skip over white space... */
  924.       value++;
  925.     }
  926.     for (end = value; *end && *end != '\n'; end++)
  927.     {
  928.       /* find end of line... */
  929.     }
  930.     *end = '\0';
  931. #ifdef DEBUG
  932.         printf("Keyword = `%s', value = `%s'\n", keyword, value);
  933. #endif
  934.     if (strcasecmp("current-printer", keyword) == 0) {
  935.       if (current_printer)
  936.         g_free (current_printer);
  937.       current_printer = g_strdup(value);
  938.     } else if (strcasecmp("printer", keyword) == 0) {
  939.       /* Switch to printer named VALUE */
  940.       add_printer(&key, 0);
  941. #ifdef DEBUG
  942.       printf("output_to is now %s\n", stp_get_output_to(p->v));
  943. #endif
  944.  
  945.       initialize_printer(&key);
  946.       strncpy(key.name, value, 127);
  947.     } else if (strcasecmp("destination", keyword) == 0) {
  948.       stp_set_output_to(key.v, value);
  949.     } else if (strcasecmp("driver", keyword) == 0) {
  950.       stp_set_driver(key.v, value);
  951.     } else if (strcasecmp("ppd-file", keyword) == 0) {
  952.       stp_set_ppd_file(key.v, value);
  953.     } else if (strcasecmp("output-type", keyword) == 0) {
  954.       stp_set_output_type(key.v, atoi(value));
  955.     } else if (strcasecmp("resolution", keyword) == 0) {
  956.       stp_set_resolution(key.v, value);
  957.     } else if (strcasecmp("media-size", keyword) == 0) {
  958.       stp_set_media_size(key.v, value);
  959.     } else if (strcasecmp("media-type", keyword) == 0) {
  960.       stp_set_media_type(key.v, value);
  961.     } else if (strcasecmp("media-source", keyword) == 0) {
  962.       stp_set_media_source(key.v, value);
  963.     } else if (strcasecmp("brightness", keyword) == 0) {
  964.       stp_set_brightness(key.v, atof(value));
  965.     } else if (strcasecmp("scaling", keyword) == 0) {
  966.       stp_set_scaling(key.v, atof(value));
  967.     } else if (strcasecmp("orientation", keyword) == 0) {
  968.       stp_set_orientation(key.v, atoi(value));
  969.     } else if (strcasecmp("left", keyword) == 0) {
  970.       stp_set_left(key.v, atoi(value));
  971.     } else if (strcasecmp("top", keyword) == 0) {
  972.       stp_set_top(key.v, atoi(value));
  973.     } else if (strcasecmp("gamma", keyword) == 0) {
  974.       stp_set_gamma(key.v, atof(value));
  975.     } else if (strcasecmp("contrast", keyword) == 0) {
  976.       stp_set_contrast(key.v, atof(value));
  977.     } else if (strcasecmp("cyan", keyword) == 0) {
  978.       stp_set_cyan(key.v, atof(value));
  979.     } else if (strcasecmp("magenta", keyword) == 0) {
  980.       stp_set_magenta(key.v, atof(value));
  981.     } else if (strcasecmp("yellow", keyword) == 0) {
  982.       stp_set_yellow(key.v, atof(value));
  983.     } else if (strcasecmp("linear", keyword) == 0) {
  984.       /* Ignore linear */
  985.     } else if (strcasecmp("image-type", keyword) == 0) {
  986.       stp_set_image_type(key.v, atoi(value));
  987.     } else if (strcasecmp("saturation", keyword) == 0) {
  988.       stp_set_saturation(key.v, atof(value));
  989.     } else if (strcasecmp("density", keyword) == 0) {
  990.       stp_set_density(key.v, atof(value));
  991.     } else if (strcasecmp("ink-type", keyword) == 0) {
  992.       stp_set_ink_type(key.v, value);
  993.     } else if (strcasecmp("dither-algorithm", keyword) == 0) {
  994.       stp_set_dither_algorithm(key.v, value);
  995.     } else if (strcasecmp("unit", keyword) == 0) {
  996.       stp_set_unit(key.v, atoi(value));
  997.     } else if (strcasecmp("custom-page-width", keyword) == 0) {
  998.       stp_set_page_width(key.v, atoi(value));
  999.     } else if (strcasecmp("custom-page-height", keyword) == 0) {
  1000.       stp_set_page_height(key.v, atoi(value));
  1001.     } else {
  1002.       /* Unrecognised keyword; ignore it... */
  1003.           printf("Unrecognized keyword `%s' in printrc; value `%s'\n", keyword, value);
  1004.     }
  1005.       }
  1006.       else
  1007.       {
  1008.        /*
  1009.         * We cannot read this file format...
  1010.         */
  1011.       }
  1012.     }
  1013.     if (format > 0)
  1014.       add_printer(&key, 0);
  1015.     fclose(fp);
  1016.   }
  1017.  
  1018.   g_free (filename);
  1019.  
  1020.  /*
  1021.   * Select the current printer as necessary...
  1022.   */
  1023.  
  1024.   if (format == 1)
  1025.   {
  1026.     if (current_printer)
  1027.     {
  1028.       for (i = 0; i < plist_count; i ++)
  1029.         if (strcmp(current_printer, plist[i].name) == 0)
  1030.       plist_current = i;
  1031.     }
  1032.   }
  1033.   else
  1034.   {
  1035.     if (stp_get_output_to(vars)[0] != '\0')
  1036.     {
  1037.       for (i = 0; i < plist_count; i ++)
  1038.         if (strcmp(stp_get_output_to(vars), stp_get_output_to(plist[i].v))== 0)
  1039.           break;
  1040.  
  1041.       if (i < plist_count)
  1042.         plist_current = i;
  1043.     }
  1044.   }
  1045. }
  1046.  
  1047. /*
  1048.  * 'printrc_save()' - Save the current printer resource configuration.
  1049.  */
  1050. void
  1051. printrc_save(void)
  1052. {
  1053.   FILE        *fp;        /* Printrc file */
  1054.   char           *filename;    /* Printrc filename */
  1055.   int        i;        /* Looping var */
  1056.   gp_plist_t    *p;        /* Current printer */
  1057.  
  1058.  /*
  1059.   * Generate the filename for the current user...
  1060.   */
  1061.  
  1062.   filename = gimp_personal_rc_file ("printrc");
  1063.  
  1064. #ifdef __EMX__
  1065.   _fnslashify(filename);
  1066. #endif
  1067.  
  1068. #ifndef __EMX__
  1069.   if ((fp = fopen(filename, "w")) != NULL)
  1070. #else
  1071.   if ((fp = fopen(filename, "wt")) != NULL)
  1072. #endif
  1073.   {
  1074.    /*
  1075.     * Write the contents of the printer list...
  1076.     */
  1077.  
  1078. #ifdef DEBUG
  1079.     fprintf(stderr, "Number of printers: %d\n", plist_count);
  1080. #endif
  1081.  
  1082.     fputs("#PRINTRCv1 written by GIMP-PRINT " PLUG_IN_VERSION "\n", fp);
  1083.  
  1084.     fprintf(fp, "Current-Printer: %s\n", plist[plist_current].name);
  1085.  
  1086.     for (i = 0, p = plist; i < plist_count; i ++, p ++)
  1087.       {
  1088.     fprintf(fp, "\nPrinter: %s\n", p->name);
  1089.     fprintf(fp, "Destination: %s\n", stp_get_output_to(p->v));
  1090.     fprintf(fp, "Driver: %s\n", stp_get_driver(p->v));
  1091.     fprintf(fp, "PPD-File: %s\n", stp_get_ppd_file(p->v));
  1092.     fprintf(fp, "Output-Type: %d\n", stp_get_output_type(p->v));
  1093.     fprintf(fp, "Resolution: %s\n", stp_get_resolution(p->v));
  1094.     fprintf(fp, "Media-Size: %s\n", stp_get_media_size(p->v));
  1095.     fprintf(fp, "Media-Type: %s\n", stp_get_media_type(p->v));
  1096.     fprintf(fp, "Media-Source: %s\n", stp_get_media_source(p->v));
  1097.     fprintf(fp, "Brightness: %.3f\n", stp_get_brightness(p->v));
  1098.     fprintf(fp, "Scaling: %.3f\n", stp_get_scaling(p->v));
  1099.     fprintf(fp, "Orientation: %d\n", stp_get_orientation(p->v));
  1100.     fprintf(fp, "Left: %d\n", stp_get_left(p->v));
  1101.     fprintf(fp, "Top: %d\n", stp_get_top(p->v));
  1102.     fprintf(fp, "Gamma: %.3f\n", stp_get_gamma(p->v));
  1103.     fprintf(fp, "Contrast: %.3f\n", stp_get_contrast(p->v));
  1104.     fprintf(fp, "Cyan: %.3f\n", stp_get_cyan(p->v));
  1105.     fprintf(fp, "Magenta: %.3f\n", stp_get_magenta(p->v));
  1106.     fprintf(fp, "Yellow: %.3f\n", stp_get_yellow(p->v));
  1107.     fprintf(fp, "Image-Type: %d\n", stp_get_image_type(p->v));
  1108.     fprintf(fp, "Saturation: %.3f\n", stp_get_saturation(p->v));
  1109.     fprintf(fp, "Density: %.3f\n", stp_get_density(p->v));
  1110.     fprintf(fp, "Ink-Type: %s\n", stp_get_ink_type(p->v));
  1111.     fprintf(fp, "Dither-Algorithm: %s\n", stp_get_dither_algorithm(p->v));
  1112.     fprintf(fp, "Unit: %d\n", stp_get_unit(p->v));
  1113.     fprintf(fp, "Custom-Page-Width: %d\n", stp_get_page_width(p->v));
  1114.     fprintf(fp, "Custom-Page-Height: %d\n", stp_get_page_height(p->v));
  1115.  
  1116. #ifdef DEBUG
  1117.         fprintf(stderr, "Wrote printer %d: %s\n", i, p->name);
  1118. #endif
  1119.  
  1120.       }
  1121.     fclose(fp);
  1122.   } else {
  1123.     fprintf(stderr,"could not open printrc file \"%s\"\n",filename);
  1124.   }
  1125.   g_free (filename);
  1126. }
  1127.  
  1128. /*
  1129.  * 'compare_printers()' - Compare system printer names for qsort().
  1130.  */
  1131.  
  1132. static int
  1133. compare_printers(gp_plist_t *p1,    /* I - First printer to compare */
  1134.                  gp_plist_t *p2)    /* I - Second printer to compare */
  1135. {
  1136.   return (strcmp(p1->name, p2->name));
  1137. }
  1138.  
  1139. /*
  1140.  * 'get_system_printers()' - Get a complete list of printers from the spooler.
  1141.  */
  1142.  
  1143. #define PRINTERS_NONE    0
  1144. #define PRINTERS_LPC    1
  1145. #define PRINTERS_LPSTAT    2
  1146.  
  1147. static void
  1148. get_system_printers(void)
  1149. {
  1150.   int   i;            /* Looping var */
  1151.   int    type;            /* 0 = none, 1 = lpc, 2 = lpstat */
  1152.   char    command[255];        /* Command to run */
  1153.   char  defname[128];        /* Default printer name */
  1154.   FILE *pfile;            /* Pipe to status command */
  1155.   char  line[255];        /* Line from status command */
  1156.   char    *ptr;            /* Pointer into line */
  1157.   char  name[128];        /* Printer name from status command */
  1158. #ifdef __EMX__
  1159.   BYTE  pnum;
  1160. #endif
  1161.   static const char    *lpcs[] =    /* Possible locations of LPC... */
  1162.         {
  1163.           "/etc"
  1164.           "/usr/bsd",
  1165.           "/usr/etc",
  1166.           "/usr/libexec",
  1167.           "/usr/sbin"
  1168.         };
  1169.  
  1170.  /*
  1171.   * Setup defaults...
  1172.   */
  1173.  
  1174.   defname[0] = '\0';
  1175.  
  1176.   check_plist(1);
  1177.   plist_count = 1;
  1178.   initialize_printer(&plist[0]);
  1179.   strcpy(plist[0].name, _("File"));
  1180.   stp_set_driver(plist[0].v, "ps2");
  1181.   stp_set_output_type(plist[0].v, OUTPUT_COLOR);
  1182.  
  1183.  /*
  1184.   * Figure out what command to run...  We use lpstat if it is available over
  1185.   * lpc since Solaris, CUPS, etc. provide both commands.  No need to list
  1186.   * each printer twice...
  1187.   */
  1188.  
  1189.   if (!access("/usr/bin/lpstat", X_OK))
  1190.   {
  1191.     strcpy(command, "/usr/bin/lpstat -d -p");
  1192.     type = PRINTERS_LPSTAT;
  1193.   }
  1194.   else
  1195.   {
  1196.     for (i = 0; i < (sizeof(lpcs) / sizeof(lpcs[0])); i ++)
  1197.     {
  1198.       sprintf(command, "%s/lpc", lpcs[i]);
  1199.  
  1200.       if (!access(command, X_OK))
  1201.         break;
  1202.     }
  1203.  
  1204.     if (i < (sizeof(lpcs) / sizeof(lpcs[0])))
  1205.     {
  1206.       strcat(command, " status < /dev/null");
  1207.       type = PRINTERS_LPC;
  1208.     }
  1209.     else
  1210.       type = PRINTERS_NONE;
  1211.   }
  1212.  
  1213.  /*
  1214.   * Run the command, if any, to get the available printers...
  1215.   */
  1216.  
  1217.   if (type > PRINTERS_NONE)
  1218.   {
  1219.     if ((pfile = popen(command, "r")) != NULL)
  1220.     {
  1221.      /*
  1222.       * Read input as needed...
  1223.       */
  1224.  
  1225.       while (fgets(line, sizeof(line), pfile) != NULL)
  1226.         switch (type)
  1227.     {
  1228.       char *result;
  1229.       case PRINTERS_LPC :
  1230.           if (!strncmp(line, "Press RETURN to continue", 24) &&
  1231.           (ptr = strchr(line, ':')) != NULL &&
  1232.           (strlen(ptr) - 2) < (ptr - line))
  1233.         strcpy(line, ptr + 2);
  1234.  
  1235.           if ((ptr = strchr(line, ':')) != NULL &&
  1236.               line[0] != ' ' && line[0] != '\t')
  1237.               {
  1238.         check_plist(plist_count + 1);
  1239.         *ptr = '\0';
  1240.         initialize_printer(&plist[plist_count]);
  1241.         strncpy(plist[plist_count].name, line,
  1242.             sizeof(plist[plist_count].name) - 1);
  1243. #ifdef DEBUG
  1244.                 fprintf(stderr, "Adding new printer from lpc: <%s>\n",
  1245.                   line);
  1246. #endif
  1247.         result = g_strdup_printf("lpr -P%s -l", line);
  1248.         stp_set_output_to(plist[plist_count].v, result);
  1249.         g_free(result);
  1250.         stp_set_driver(plist[plist_count].v, "ps2");
  1251.         plist_count ++;
  1252.           }
  1253.           break;
  1254.  
  1255.       case PRINTERS_LPSTAT :
  1256.           if ((sscanf(line, "printer %127s", name) == 1) ||
  1257.           (sscanf(line, "Printer: %127s", name) == 1))
  1258.           {
  1259.         check_plist(plist_count + 1);
  1260.         initialize_printer(&plist[plist_count]);
  1261.         strncpy(plist[plist_count].name, name,
  1262.             sizeof(plist[plist_count].name) - 1);
  1263. #ifdef DEBUG
  1264.                 fprintf(stderr, "Adding new printer from lpc: <%s>\n",
  1265.                   name);
  1266. #endif
  1267.         result = g_strdup_printf("lp -s -d%s -oraw", name);
  1268.         stp_set_output_to(plist[plist_count].v, result);
  1269.         g_free(result);
  1270.         stp_set_driver(plist[plist_count].v, "ps2");
  1271.             plist_count ++;
  1272.           }
  1273.           else
  1274.             sscanf(line, "system default destination: %127s", defname);
  1275.           break;
  1276.     }
  1277.  
  1278.       pclose(pfile);
  1279.     }
  1280.   }
  1281.  
  1282. #ifdef __EMX__
  1283.   if (DosDevConfig(&pnum, DEVINFO_PRINTER) == NO_ERROR)
  1284.     {
  1285.       for (i = 1; i <= pnum; i++)
  1286.     {
  1287.       check_plist(plist_count + 1);
  1288.       initialize_printer(&plist[plist_count]);
  1289.       sprintf(plist[plist_count].name, "LPT%d:", i);
  1290.       sprintf(plist[plist_count].v.output_to, "PRINT /D:LPT%d /B ", i);
  1291.           strcpy(plist[plist_count].v.driver, "ps2");
  1292.           plist_count ++;
  1293.     }
  1294.     }
  1295. #endif
  1296.  
  1297.   if (plist_count > 2)
  1298.     qsort(plist + 1, plist_count - 1, sizeof(gp_plist_t),
  1299.           (int (*)(const void *, const void *))compare_printers);
  1300.  
  1301.   if (defname[0] != '\0' && stp_get_output_to(vars)[0] == '\0')
  1302.   {
  1303.     for (i = 0; i < plist_count; i ++)
  1304.       if (strcmp(defname, plist[i].name) == 0)
  1305.         break;
  1306.  
  1307.     if (i < plist_count)
  1308.       plist_current = i;
  1309.   }
  1310. }
  1311.  
  1312. /*
  1313.  * End of "$Id: print.c,v 1.43.2.2 2002/07/09 16:48:00 neo Exp $".
  1314.  */
  1315.